// 根据官方文档建议，几千条数据直接交前端处理合适，有处理10万条效率仍不错的案例。
"use client";
import React from "react";
import {
  ColumnDef,
  ColumnFiltersState,
  PaginationState,
  SortingState,
  TableState,
  Updater,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getExpandedRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
  ColumnPinningState,
} from "@tanstack/react-table";
import { useForm } from "react-hook-form";

import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Heading } from "@/components/ui/heading";
import { Separator } from "@/components/ui/separator";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { ChevronsLeft, ChevronsRight } from "lucide-react";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { useTableUrlSearchParams } from "@/hooks/useTableUrlSearchParams";
import { useTableSearchParams } from "@/hooks/useTableSearchParams";
import { DropzoneFileUploader } from "@/components/ui/file-uploader";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from "./dropdown-menu";

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
  totalCount: number; // 分片取数时不能用data.length计算页数
  defaultFilterColumn: string;
  manualFiltering?: boolean;
  initColumnVisibility?: { [key: string]: boolean }; // 不显示但row.getValue()仍然能取到值
  initRowSelection?: { [key: string]: boolean }; // 不显示但row.getValue()仍然能取到值
  getRowId?: (originalRow: TData, index: number, parent?: any) => string;
  pageSizeOptions?: number[];
  synchroniseUrl?: boolean; // 将参数同步到URL供父组件重新取数
  showImportButton?: boolean;
  onSubmitFiles?: (values: File[]) => Promise<any>;
  onSelectionChange?: (values: { [key: string]: boolean }) => void;
}

const CustomTable: React.FC<DataTableProps<any, any>> = ({
  columns,
  data,
  totalCount,
  defaultFilterColumn,
  manualFiltering = true,
  initColumnVisibility = {},
  initRowSelection = {},
  getRowId = (originalRow, index, parent) => {
    return originalRow.id || index;
  },
  pageSizeOptions = [10, 30, 50, 100, 300],
  synchroniseUrl = true,
  showImportButton = false,
  onSubmitFiles,
  onSelectionChange,
}) => {
  const {
    pageIndex,
    pageSize,
    search,
    sorting,
    columnFilters,
    setTableUrlSearchParams,
  } = useTableUrlSearchParams();
  const {
    pageIndex: localPageIndex,
    pageSize: localPageSize,
    search: localSearch,
    sorting: localSorting,
    columnFilters: localColumnFilters,
    setTableSearchParams,
  } = useTableSearchParams();
  const [pageCount, setPageCount] = React.useState<number>(0);
  const [isSubmitting, setIsSubmitting] = React.useState<boolean>(false);
  const [columnVisibility, setColumnVisibility] =
    React.useState<VisibilityState>(initColumnVisibility);
  const [columnOrder, setColumnOrder] = React.useState<string[]>(() =>
    columns.map((c) => c.id!)
  );
  const [columnPinning, setColumnPinning] = React.useState<ColumnPinningState>({
    left: ["select"],
    right: ["actions"],
  });
  const [rowSelection, setRowSelection] = React.useState(initRowSelection);
  const [pagination, setPagination] = React.useState(
    synchroniseUrl
      ? {
          pageIndex,
          pageSize,
        }
      : { pageIndex: localPageIndex, pageSize: localPageSize }
  );
  const [filterColumn, setFilterColumn] = React.useState<any>();
  const [multiColumnFilter, setMultiColumnFilter] = React.useState<boolean>();

  // 定义文件的最大大小限制（例如 5MB）
  const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5 MB

  // 自定义验证函数，用于检查文件大小和类型
  const fileValidator = z.instanceof(File).refine(
    (file) => {
      // 检查文件大小
      if (file.size > MAX_FILE_SIZE) {
        return false;
      }

      // 检查 MIME 类型
      const allowedMimeTypes = ["image/jpeg", "image/png"];
      if (!allowedMimeTypes.includes(file.type)) {
        return false;
      }

      // 文件通过所有检查
      return true;
    },
    {
      message: "File must be less than 5MB and must be a JPEG or PNG image.",
    }
  );

  // 定义包含文件的表单模式
  const formSchema = z.object({
    // file: fileValidator,
    files: z.any().array(),
  });

  type FormValuesT = z.infer<typeof formSchema>;

  const [isDialogOpen, setIsDialogOpen] = React.useState<boolean>();
  const defaultValues = {
    files: [],
  };
  const form = useForm<FormValuesT>({
    resolver: zodResolver(formSchema),
    defaultValues: defaultValues,
  });

  const handleFormSubmit = React.useCallback(async (values: any) => {
    // to-do 添加校验
    // form.trigger()
    if (onSubmitFiles) {
      try {
        setIsSubmitting(true);
        const result = await onSubmitFiles(values);
        console.log(result);
        setIsSubmitting(false);
      } finally {
        setIsSubmitting(false);
      }
    }
  }, []);

  React.useEffect(() => {
    if (synchroniseUrl) {
      setPageCount(Math.ceil(totalCount / (pageSize || 10)));
    } else {
      setPageCount(Math.ceil(totalCount / (localPageSize || 10)));
    }
  }, [totalCount, pageSize, localPageSize]);

  React.useEffect(() => {
    const result = columns.find((column) => {
      // console.log(column);
      // console.log(column.id);
      // column的id属性通常要明确赋值，如果没有的话会从accessorKey和header属性生成。
      return "id" in column && column.id == defaultFilterColumn;
    });
    setFilterColumn(result);
  }, [defaultFilterColumn]);

  const table = useReactTable({
    data,
    columns,
    pageCount: pageCount ?? -1,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(), // 客户端检索时必须项，服务端检索过滤时不用
    manualFiltering: manualFiltering, // 自己服务器端检索过滤
    getExpandedRowModel: getExpandedRowModel(),
    filterFromLeafRows: true,
    maxLeafRowFilterDepth: 1,
    onColumnVisibilityChange: setColumnVisibility,
    onColumnOrderChange: setColumnOrder,
    columnResizeMode: "onChange",
    // onRowSelectionChange: setRowSelection,
    onRowSelectionChange: (updater) => {
      setRowSelection((old) => {
        const newRowSelectionValue =
          updater instanceof Function ? updater(old) : updater;
        console.log(newRowSelectionValue);
        onSelectionChange && onSelectionChange(newRowSelectionValue);
        return newRowSelectionValue;
      });
    },
    onPaginationChange: (updater) => {
      setPagination((old) => {
        const newPaginationValue =
          updater instanceof Function ? updater(old) : updater;
        if (synchroniseUrl) {
          setTableUrlSearchParams({
            pageIndex: newPaginationValue.pageIndex,
            pageSize: newPaginationValue.pageSize,
          });
        } else {
          setTableSearchParams({
            pageIndex: newPaginationValue.pageIndex,
            pageSize: newPaginationValue.pageSize,
          });
        }
        return newPaginationValue;
      });
    },
    onSortingChange: (updater) => {
      const newSortingValue =
        updater instanceof Function ? updater(sorting) : updater;
      // console.log(newSortingValue);
      if (synchroniseUrl) {
        setTableUrlSearchParams({
          sorting: newSortingValue,
        });
      } else {
        setTableSearchParams({
          sorting: newSortingValue,
        });
      }
    },
    onColumnFiltersChange: (updater) => {
      const newColumnFiltersValue =
        updater instanceof Function ? updater(columnFilters) : updater;
      // console.log(newColumnFiltersValue);
      const currentFilter = newColumnFiltersValue.find(
        (item) => item.id == filterColumn.id
      );
      // console.log(currentFilter);
      // 当前检索字段有值时才能检索到，空值不会存在
      if (currentFilter) {
        if (multiColumnFilter) {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          } else {
            setTableSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          }
        } else {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: [currentFilter],
            });
          } else {
            setTableSearchParams({
              columnFilters: [currentFilter],
            });
          }
        }
      } else {
        if (multiColumnFilter) {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          } else {
            setTableSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          }
        } else {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: [],
            });
          } else {
            setTableSearchParams({
              columnFilters: [],
            });
          }
        }
      }
    },
    state: {
      sorting: synchroniseUrl ? sorting : localSorting,
      columnFilters: synchroniseUrl ? columnFilters : localColumnFilters,
      columnVisibility,
      columnOrder,
      columnPinning,
      rowSelection,
      pagination: synchroniseUrl
        ? { pageIndex, pageSize }
        : { pageIndex: localPageIndex, pageSize: localPageSize },
    },
    enableColumnResizing: true,
    defaultColumn: {
      size: 100,
      minSize: 100,
      maxSize: 250,
    },
    getRowId: getRowId,
    manualPagination: false, // 设置为true时会把传入的data在第一页全展示
  });

  if (filterColumn) {
    const searchValue = table
      .getColumn(filterColumn.id)
      ?.getFilterValue() as string;
  }

  return (
    <>
      <div className="flex justify-between">
        {filterColumn && (
          <div className="flex space-x-3">
            <Select
              onValueChange={(value) => {
                console.log(value);
                const result = columns.find((column) => {
                  // console.log(column);
                  return column.id == value;
                });
                if (result) {
                  console.log(result);
                  setFilterColumn(result);
                }
              }}
            >
              <SelectTrigger className="w-[170px]">
                <SelectValue
                  placeholder={
                    filterColumn &&
                    filterColumn.header &&
                    filterColumn.header instanceof Function
                      ? filterColumn.header()
                      : filterColumn.header
                  }
                />
              </SelectTrigger>
              <SelectContent>
                {table
                  .getAllColumns()
                  .filter((column) => column.getCanFilter())
                  .map((column) => {
                    // console.log(column);
                    return (
                      <SelectItem
                        key={column.id}
                        value={column.id}
                        className="capitalize"
                      >
                        {column &&
                        column.columnDef.header &&
                        column.columnDef.header instanceof Function
                          ? column.columnDef.header(null as any)
                          : column.columnDef.header}
                      </SelectItem>
                    );
                  })}
              </SelectContent>
            </Select>
            <Input
              placeholder={`Search ${filterColumn.id}...`}
              value={
                (table
                  .getColumn(filterColumn.id)
                  ?.getFilterValue() as string) ?? ""
              }
              onChange={(event) => {
                table
                  .getColumn(filterColumn.id)
                  ?.setFilterValue(event.target.value);
                if (synchroniseUrl) {
                  // 检索关键词变化时要将页索引重置为0
                  setTableUrlSearchParams({
                    search: event.target.value,
                    pageIndex: 0,
                  });
                } else {
                  setTableSearchParams({
                    search: event.target.value,
                    pageIndex: 0,
                  });
                }
              }}
              className="w-full md:max-w-sm"
            />
            <div className="flex items-center space-x-2">
              <Checkbox
                checked={multiColumnFilter}
                onCheckedChange={(value) => {
                  console.log(value);
                  setMultiColumnFilter(!multiColumnFilter);
                }}
              />
              <span className="w-[80px]">组合条件</span>
            </div>
          </div>
        )}
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="outline" className="ml-auto">
              选择展示列
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            {table
              .getAllColumns()
              .filter((column) => column.getCanHide())
              .map((column) => {
                // console.log(column.columnDef);
                // console.log(column.columnDef.header);
                return (
                  <DropdownMenuCheckboxItem
                    key={column.id}
                    className="capitalize"
                    checked={column.getIsVisible()}
                    onCheckedChange={(value) =>
                      column.toggleVisibility(!!value)
                    }
                  >
                    {/* {typeof column.columnDef.header == "string"
                      ? column.columnDef.header
                      : column.id} */}
                    {column &&
                    column.columnDef &&
                    column.columnDef.header &&
                    column.columnDef.header instanceof Function
                      ? column.columnDef.header(null as any)
                      : column.columnDef.header}
                  </DropdownMenuCheckboxItem>
                );
              })}
          </DropdownMenuContent>
        </DropdownMenu>
        {showImportButton && (
          <Button onClick={() => setIsDialogOpen(!isDialogOpen)}>
            批量导入
          </Button>
        )}
      </div>
      <ScrollArea className="h-[calc(80vh-30px)] rounded-md border">
        <Table className="relative">
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => {
              // console.log(headerGroup);
              return (
                <TableRow key={headerGroup.id}>
                  {headerGroup.headers.map((header) => {
                    return (
                      <TableHead
                        style={{
                          width: `${header.column.columnDef.size}px`,
                          minWidth: `${header.column.columnDef.minSize}px`,
                          maxWidth: `${header.column.columnDef.maxSize}px`,
                        }}
                        key={header.id}
                      >
                        {header.isPlaceholder
                          ? null
                          : flexRender(
                              header.column.columnDef.header,
                              header.getContext()
                            )}
                      </TableHead>
                    );
                  })}
                </TableRow>
              );
            })}
          </TableHeader>
          <TableBody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow
                  key={row.id}
                  data-state={row.getIsSelected() && "selected"}
                >
                  {row.getVisibleCells().map((cell) => {
                    return (
                      <TableCell key={cell.id}>
                        {flexRender(
                          cell.column.columnDef.cell,
                          cell.getContext()
                        )}
                      </TableCell>
                    );
                  })}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell
                  colSpan={columns.length}
                  className="h-24 text-center"
                >
                  暂无数据
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
        <ScrollBar orientation="horizontal" />
      </ScrollArea>

      <div className="flex flex-col items-center justify-end gap-2 space-x-2 py-4 sm:flex-row">
        <div className="flex w-full items-center justify-between">
          <div className="flex-1 text-sm text-muted-foreground">
            <span>选择了</span>{" "}
            {table.getFilteredSelectedRowModel().rows.length} <span>行</span>
          </div>
          <div className="flex flex-col items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8">
            <div className="flex items-center space-x-2">
              <p className="whitespace-nowrap text-sm font-medium">每页</p>
              <Select
                value={`${table.getState().pagination.pageSize}`}
                onValueChange={(value) => {
                  table.setPageSize(Number(value));
                }}
              >
                <SelectTrigger className="h-8 w-[70px]">
                  <SelectValue
                    placeholder={table.getState().pagination.pageSize}
                  />
                </SelectTrigger>
                <SelectContent side="top">
                  {pageSizeOptions.map((pageSize) => (
                    <SelectItem key={pageSize} value={`${pageSize}`}>
                      {pageSize}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <p className="whitespace-nowrap text-sm font-medium">行</p>
            </div>
          </div>
        </div>
        {/* 翻页工具 */}
        <div className="flex w-full items-center justify-between gap-2 sm:justify-end">
          <div className="flex w-[100px] items-center justify-center text-sm font-medium">
            {table.getState().pagination.pageIndex + 1} / {table.getPageCount()}
          </div>
          <div className="flex items-center space-x-2">
            <Button
              aria-label="Go to first pageIndex"
              variant="outline"
              className="hidden h-8 w-8 p-0 lg:flex"
              onClick={() => table.setPageIndex(0)}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronsLeft className="h-4 w-4" aria-hidden="true" />
            </Button>
            <Button
              aria-label="Go to previous pageIndex"
              variant="outline"
              className="h-8 w-8 p-0"
              onClick={(e) => {
                e.preventDefault();
                table.previousPage();
              }}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronLeftIcon className="h-4 w-4" aria-hidden="true" />
            </Button>
            <Button
              aria-label="Go to next pageIndex"
              variant="outline"
              className="h-8 w-8 p-0"
              onClick={(e) => {
                e.preventDefault();
                table.nextPage();
              }}
              disabled={!table.getCanNextPage()}
            >
              <ChevronRightIcon className="h-4 w-4" aria-hidden="true" />
            </Button>
            <Button
              aria-label="Go to last pageIndex"
              variant="outline"
              className="hidden h-8 w-8 p-0 lg:flex"
              onClick={() => table.setPageIndex(table.getPageCount() - 1)}
              disabled={!table.getCanNextPage()}
            >
              <ChevronsRight className="h-4 w-4" aria-hidden="true" />
            </Button>
          </div>
        </div>
        {/* 批量导入文件提交文件对话框 */}
        <Dialog
          open={isDialogOpen}
          onOpenChange={() => setIsDialogOpen(!isDialogOpen)}
        >
          <DialogContent className="max-w-3xl overflow-y-auto">
            <DialogHeader>
              <DialogTitle></DialogTitle>
              <DialogDescription></DialogDescription>
            </DialogHeader>
            <div className="flex items-center justify-between">
              <Heading title="Excel批量导入数据" description={""} />
            </div>
            <Separator />
            <Form {...form}>
              <form
                onSubmit={form.handleSubmit(handleFormSubmit)}
                className="w-full space-y-8 flex flex-col justify-center"
              >
                <div className="flex flex-col gap-4">
                  <FormField
                    control={form.control}
                    name="files"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          <DropzoneFileUploader
                            value={field.value}
                            onChange={field.onChange}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </div>
                <Button
                  disabled={isSubmitting}
                  className="ml-auto"
                  type="submit"
                >
                  提交
                </Button>
              </form>
            </Form>
          </DialogContent>
        </Dialog>
      </div>
    </>
  );
};

export default CustomTable;
